package network.server;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;

import state.Globals;
import system.GroupDispatcherMain;

import network.BaseModeHandler;
import network.ConnectionMode;
import network.handlers.ElevatorModeHandler;
import network.handlers.ObserverModeHandler;
import network.handlers.PersonDispatcherModeHandler;
import network.handlers.RegistrationModeHandler;
import network.server.SocketThread;

import messages.BaseMessage;
import messages.KillOrderMessage;
import messages.MessageFactory;
import messages.MessageType;

public class ModeHandlerThread extends SocketThread {

    private byte clientId = 0;
    private BaseModeHandler curHandler;

    public ModeHandlerThread(ConnectionListenerThread parent, Socket sockToHandle)
    {
        super(parent, sockToHandle);
    }

    @Override
    public void runThread()
    {
        curHandler = new RegistrationModeHandler(this);
        curHandler.enterMode(clientId);

        while (shouldContinue)
        {
            if (!remoteSock.isConnected())
            {
                break;
            }
            
            BaseMessage message = null; // receive a message
            try
            {
                message = MessageFactory.readMessage(remoteSock, 2);
            }
            catch (SocketTimeoutException e)
            {
            	//IGNORE
            	continue;
            }
            catch (IOException e)
            {
                Globals.getLogger().error("Error occurred while attempting to receive a message", e);

                shouldContinue = false;
            }
            
            if (!shouldContinue)
            {
                break;
            }
            
            if (message != null && message.getMessageType() == MessageType.KillOrderMessage)
            {
            	KillOrderMessage mess = (KillOrderMessage) message;
            	if (mess.isKillOrder())
            	{
            	    Globals.getLogger().log("Received a KillOrderMessage!  Shutting down the system!");
            		
            	    this.getParent().removeChild(this);
            	    
            	    GroupDispatcherMain.shutdownSystem();
            	    
            	    System.exit(0);
            	}
            }

            ConnectionMode nextMode = curHandler.handleMessage(message);

            if (nextMode != curHandler.getMode())
            {
                curHandler.exitMode();
                switch (nextMode)
                {
                    case Closed:
                        shouldContinue = false;
                        break;
                    case Elevator:
                        curHandler = new ElevatorModeHandler(this);
                        curHandler.enterMode(clientId);
                        break;
                    case Observer:
                        curHandler = new ObserverModeHandler(this);
                        curHandler.enterMode(clientId);
                        break;
                    case Registration:
                        curHandler = new RegistrationModeHandler(this);
                        curHandler.enterMode(clientId);
                        break;
                    case PersonDispatcher:
                    	curHandler = new PersonDispatcherModeHandler(this);
                    	curHandler.enterMode(clientId);
                        break;
                }
            }
        }
    }

    public byte getClientId()
    {
        return clientId;
    }

    public void setClientId(byte clientId)
    {
        this.clientId = clientId;
    }

}
